/*
 * @Author: 郝奔 1425466221@qq.com
 * @Date: 2024-12-02 16:31:43
 * @LastEditors: miteng 973203639@qq.com
 * @LastEditTime: 2025-03-13 14:21:36
 * @FilePath: /weshyper-integratedplatform-web/src/framework/store/modules/permission.ts
 * @Description: 
 * Copyright (c) 2024-present HBIS Digital Technology Co.,Ltd. All rights reserved. 
 */
import { RouteRecordRaw } from 'vue-router';
import { defineStore } from 'pinia';
import { routes as constantRoutes } from '@/router';
import { store } from '@/store';
import { getFunctionInfoByAppCode } from '@/framework/api/menu';
import { AppRoutesData, LeftMenuType, ParentTitleType } from '@/framework/api/menu/types';
import { isExternal } from '@/utils/validate';
import { upperCamelCase } from '@/framework/utils/index';
import { deepClone } from '@/framework/utils/index';
import { ref } from 'vue';
import IframePageView from '@/framework/views/layouts/IframePageView.vue'
const modules = { ...import.meta.glob('@/views/**/**.vue'), ...import.meta.glob('@/framework/views/**/**.vue') };
//在 TypeScript 中，void 类型表示没有任何类型，通常用于函数没有返回值的情况。然而，你这里的 layout 函数使用了动态 import() 语法，它返回一个 Promise，因为它是在运行时异步加载模块的
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const layout = (): Promise<any> => import('@/framework/layout/index.vue');
// eslint-disable-next-line @typescript-eslint/no-explicit-any
//该方法被弃用  默认有所有权限  返回值 永久为true
const hasPermission = (roles: string[], route: RouteRecordRaw): boolean => {
  if (route.meta && route.meta.roles) {
    if (roles.includes('ROOT')) {
      return true;
    }
    return roles.some(role => {
      if (route.meta?.roles !== undefined) {
        return (route.meta.roles as string[]).includes(role);
      }
    });
  }
  return true; //返回值 永久为true
};

const dealComponentPath = (component: string): string => {
  if (!component) return ''
  if (component.indexOf('.vue') > -1) {
    return component
  } else {
    return component + '.vue'
  }

}
const filterAsyncRoutes = (routes: RouteRecordRaw[], roles: string[]): RouteRecordRaw[] => {
  const res: RouteRecordRaw[] = [];

  routes.forEach(route => {
    const tmp = { ...route };
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
    // if (hasPermission(roles, tmp)) {
    //   if (tmp.component == 'layout') {
    //     tmp.component = layout;
    //   } else {
    //     const component = modules[`/src/${dealComponentPath(tmp.component)}`] as any;
    //     if (component) {
    //       tmp.component = component;
    //     } else {
    //       tmp.component = modules[`/src/views/error-page/404.vue`];
    //     }
    //   }
    //   res.push(tmp);

    //   if (tmp.children) {
    //     tmp.children = filterAsyncRoutes(tmp.children, roles);
    //   }
    // }
  });
  return res;
};

//获取第一个菜单的路由
function getFirstMenu(arr: AppRoutesData[]): string {
  for (let i = 0; i <= arr.length; i++) {
    if (!arr[i]) {
      continue
    }
    if (arr[i].menuType === 'C') {
      return arr[i].path
    }
    if (arr[i].children && arr[i].children.length) {
      const temp = getFirstMenu(arr[i].children)
      if (temp) { return temp }
    }
  }
  return ''
}

// setup
export const usePermissionStore = defineStore('permission', () => {
  // state
  const routes = ref<RouteRecordRaw[]>([]);
  const addRoutes = ref<RouteRecordRaw[]>([]);
  const appRoutes = ref<AppRoutesData[]>([]);
  const allRoutes = ref<LeftMenuType[]>([]);
  const firstPath = ref<string>()
  const buttonCodes = ref<Array<string>>([])

  // actions
  function setRoutes(newRoutes: RouteRecordRaw[]): void {
    addRoutes.value = newRoutes;
    routes.value = constantRoutes.concat(newRoutes);
  }

  function setAppRoutes(newAppRoutes: AppRoutesData[]): void {
    console.log('newAppRoutes', newAppRoutes)
    appRoutes.value = newAppRoutes;
    firstPath.value = getFirstMenu(newAppRoutes) // 找第一个路由去
  }

  function generateRoutes(roles: string[]): Promise<RouteRecordRaw[]> {
    return new Promise<RouteRecordRaw[]>((resolve, reject) => {
      getFunctionInfoByAppCode({ appCode: import.meta.env.VITE_APP_CODE })
        .then(response => {
          const data = response.data?.menuRouterDTO || [];  //路由
          buttonCodes.value = response.data?.buttonCodes || [] // 按钮权限
          const dealDataList = dealData(data)
          allRoutes.value = dealDataList
          const loadMenuData = [] as LeftMenuType[]//后端返回数据
          const asyncRoutes: RouteRecordRaw[] = []  //vue 路由数据
          const appRoutes: AppRoutesData[] = []  //前端存储数据
          Object.assign(loadMenuData, dealDataList)
          generAppMenu(asyncRoutes, loadMenuData, appRoutes)
          setAppRoutes(deepClone(asyncRoutes));
          const accessedRoutes = filterAsyncRoutes(asyncRoutes, roles);
          // const accessedRoutes = filterAsyncRoutes(data, roles);
          setRoutes(accessedRoutes);
          resolve(accessedRoutes);
        })
        .catch(error => {
          reject(error);
        });
    });
  }
  return { routes, appRoutes, setRoutes, generateRoutes, allRoutes, buttonCodes, firstPath };
});
type UsePermissionStoreType = ReturnType<typeof usePermissionStore>;
// 非setup
export function usePermissionStoreHook(): UsePermissionStoreType {
  return usePermissionStore(store);
}

function generAppMenu(routes: (RouteRecordRaw | AppRoutesData)[], data: LeftMenuType[], appRoutes: AppRoutesData[]): void {
  // 生成当前应用的路由菜单
  generaMenu(routes, data, {} as ParentTitleType) // 生成当前应用的路由菜单
  // for (const item of data) { // 遍历应用
  //   const appRoute: (RouteRecordRaw | AppRoutesData)[] = []
  //   if (item.children) {
  //     generaMenu(appRoute, item.children, {
  //       meta: {
  //         title: item.title
  //       },
  //       path: item.path
  //     }) // 生成当前应用的路由菜单
  //   }
  //   for (const app of appRoute) {
  //     routes.push(app)
  //   }
  //   appRoutes.push({
  //     path: item.path,
  //     name: item.title,
  //     hidden: item.visible == 'N',
  //     icon: item.icon,
  //     children: appRoute,
  //     meta: { title: item.title, icon: item.icon, hidden: item.visible ==  'N' }
  //   })
  // }
}
function generaMenu(routes: (RouteRecordRaw | AppRoutesData)[] | LeftMenuType[], data: LeftMenuType[], parentTitle?: ParentTitleType): void {
  // 分应用路由
  if (data != null) {
    // 遍历后台返回的菜单路由
    data.forEach(async item => {
      let menu = {} as Partial<LeftMenuType>
      // 内链地址
      if (item.component && (item.component.startsWith('/') || isExternal(item.component))) {
        menu = {
          path: item.path,
          component: IframePageView,
          // component: null,
          name: upperCamelCase(item.menuCode),
          meta: { title: item.title, icon: item.icon, parentTitle: parentTitle },
          hidden: item.visible == 'N',
          props: {
            url: item.component,
            id: item.path
          }
        } as object as Partial<LeftMenuType>
      } else if (item.path && isExternal(item.path)) { // 外链地址
        menu = {
          path: item.path,
          hidden: item.visible == 'N',
          meta: { title: item.title, icon: item.icon }
        }
      } else { // 组件
        const temp = {
          path: item.path,
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
          component: item.component === "layout" ? layout : modules[`/src/${dealComponentPath(item.component)}`] as any, // 需要让后台处理layout
          // component: item.component ? (resolve) => require([`@/${item.component === 'layout' ? 'framework/layout' : item.component}`], resolve) : AppView, // 需要让后台处理layout
          // component: item.component ,
          name: upperCamelCase(item.menuCode),
          meta: { title: item.title, icon: item.icon, parentTitle: parentTitle, noCache: false, hidden: item.visible == 'N' },
          hidden: item.visible == 'N',
          menuType: item.menuType,
          children: []
        } as Partial<LeftMenuType>
        menu = parentTitle && item.menuType === 'C' ? {
          menuType: 'layout', // 默认
          path: '/selfLayout',
          component: layout,
          children: [temp]
        } as Partial<LeftMenuType> : temp
        // menu = temp
      }

      if (item.menuType === 'M' && item.children && menu.children) {
        generaMenu(menu.children, item.children)
      }
      if (!routes) {
        routes = []
      }
      routes.push(menu as LeftMenuType)
    })
  }
}
// 处理组件下的component eg.@/framework/views/wayManage/userName=>@/framework/views/wayManage/user-name.vue
const dealComponentUrl = (component: string): string => {
  const index = component.lastIndexOf('\/')
  const lastUrl = component.substring(index + 1, component.length) // 找到最后一个/后的内容
  const str = lastUrl.replace(/([a-zA-Z])([A-Z])/g, '$1-$2').toLowerCase() //将驼峰转为中横线链接eg.addManage=>add-manage AddManage=>add-manage
  const frontUrl = component.substring(0, index + 1) // 找到最后一个/前的内容
  return `${frontUrl}${str}`
}
function dealData(data: LeftMenuType[]): LeftMenuType[] {
  data = data.map(res => {
    if ((res.component && !(res.component.startsWith('/')) && !isExternal(res.component)) && (res.path && !isExternal(res.path)) && res.component != 'layout') {
      res.component = dealComponentUrl(res.component)
    }
    if (res.children && res.children.length > 0) {
      dealData(res.children)
    }
    return res
  })
  return data
}